Token Metadata extension to form standard#2439
Token Metadata extension to form standard#2439afa7789 wants to merge 98 commits into0xMiden:nextfrom
Conversation
55282e1 to
b1dba96
Compare
|
We should also consider adding the corresponding metadata and the new constructor to the network fungible faucets: https://github.com/afa7789/miden-base/blob/f7426116833b1f76da3195738ccb838a52880f80/crates/miden-standards/src/account/faucets/network_fungible.rs#L93-L101 |
|
@afa7789 we should also add a flag and procedure to change max_supply. It's basically similar to have we have done in |
In this branch ? pr ? |
Yes, it would be better if you can have this in this PR. |
|
@bobbinth @mmagician this is ready for review :) |
bobbinth
left a comment
There was a problem hiding this comment.
Not a review - but I left a couple of comments inline. The main one is about how we can handle returning large amounts of data from account interface procedures.
|
@afa7789 Additionally, as this discussion #2423 (comment) has been concluded, you can update the PR with the following:
For
|
5548bd5 to
609b355
Compare
| /// - Slot 12–17: logo_uri (6 Words) | ||
| /// - Slot 18–23: external_link (6 Words) | ||
| #[derive(Debug, Clone, Default)] | ||
| pub struct Info { |
There was a problem hiding this comment.
Why is this not part of TokenMetadata directly?
It feels very closely related, so I would consider including it. Making it a separate component means users always need to remember to include it in their account next to TokenMetadata and need to decode both TokenMetadata and Info to get all the related data, so this pushes some complexity up the stack.
It would also be nice if we could set mutability flags directly via the mentioned TokenMetadataBuilder, e.g. TokenMetadataBuilder::new(...).description("abc").mutable_description().build().
Related, I think Info does not be an AccountComponent, since it does not have any code. This suggests it is a set of standard storage slots but not a full account component (a combination of functionality / code and storage). So in the same way as TokenMetadata is not an account component (but more like a standardized storage slot), we could make Info a reusable set of storage slots. I would then include it in TokenMetadata, which in turn is included in BasicFungibleFaucet (a proper account component). Notably, this does not prevent reusing Info for other purposes in the future (such as for NFTs).
Naming: I think this is more aptly described as TokenMetadata. This is more generic metadata than what is currently called TokenMetadata which is specific to fungible assets. So maybe it is better to rename the current TokenMetadata to FungibleTokenMetadata to free up that name for this.
|
@PhilippGackstatter I did most of the mentioned things. |
ebcbd2e to
671a9dc
Compare
ecf267b to
2e50884
Compare
bobbinth
left a comment
There was a problem hiding this comment.
Looks good! Thank you. Still not a full review, but by now I've looked at most of the code and left some more comments inline.
Overall, I'm still somewhat confused about the general organization and naming (I left a few comments about that). It seems like we don't yet have a consistent methodology worked out. The core of the issue, as I see it, is that it is not clear what is the new component we are defining - e.g., is it a "fungible faucet" component, a "token metadata" component, or a "fungible token metadata" component. Currently, it seems like we are trying a bit of everything.
This is probably in part driven by the fact that we may want to merge network and basic fungible faucets shortly, and this will have a significant impact on how things are organized. So, I think we have a couple paths:
- Try to clean this PR up as much as possible, and merge it knowing that we are not yet at a satisfactory state and will need to fix things up in a follow up.
- First merge basic and network faucets, and then update this PR with the structure that will be closer to final.
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Outdated
Show resolved
Hide resolved
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/builder.rs
Outdated
Show resolved
Hide resolved
crates/miden-agglayer/src/lib.rs
Outdated
| #[derive(Debug, Clone)] | ||
| pub struct AggLayerFaucet { | ||
| metadata: TokenMetadata, | ||
| metadata: FungibleTokenMetadata, |
There was a problem hiding this comment.
Let's roll-back the changes to the AggLayer crate in this PR, and once this is merged, we can make a follow-up PR to propagate them.
crates/miden-standards/src/account/metadata/token_metadata/mod.rs
Outdated
Show resolved
Hide resolved
PhilippGackstatter
left a comment
There was a problem hiding this comment.
Looks good. I think the overall structure is fine for now, and we can reconsider it a bit more with #2613.
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Outdated
Show resolved
Hide resolved
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Outdated
Show resolved
Hide resolved
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Outdated
Show resolved
Hide resolved
| if max_supply.as_canonical_u64() > FungibleAsset::MAX_AMOUNT { | ||
| return Err(FungibleFaucetError::MaxSupplyTooLarge { | ||
| actual: max_supply.as_canonical_u64(), | ||
| max: FungibleAsset::MAX_AMOUNT, | ||
| }); | ||
| } | ||
| if token_supply.as_canonical_u64() > max_supply.as_canonical_u64() { | ||
| return Err(FungibleFaucetError::TokenSupplyExceedsMaxSupply { |
There was a problem hiding this comment.
It would be great if we could implement validation (e.g. of max supply, token supply, ...) once and then reuse it, and also avoid instantiating the struct directly (Self { ... }) in multiple places.
Ideally, we end up with a single constructor that validates the basics and instantiates the struct, all other constructors are wrappers around this. This results in the least amount of duplication and the least chance to introduce differences in how validation works.
There was a problem hiding this comment.
We now have new_validated, could we now call it here instead of reimplementing the checks?
Self::new_validated(
symbol,
decimals,
max_supply,
token_supply,
metadata.name.ok_or_else(todo!()),
metadata.description,
metadata.logo_uri,
metadata.external_link,
);| token_metadata = token_metadata | ||
| .with_description_mutable(mutability_word[0] != Felt::ZERO) | ||
| .with_logo_uri_mutable(mutability_word[1] != Felt::ZERO) | ||
| .with_external_link_mutable(mutability_word[2] != Felt::ZERO) | ||
| .with_max_supply_mutable(mutability_word[3] != Felt::ZERO); |
There was a problem hiding this comment.
It would be good to avoid using magic numbers here, especially because if we update the layout in TokenMetadata, these changes are less likely to propagate here since this is a different module. TokenMetadata should be the only place that defines the exact layout of this mutability config word and should provide helpers for constructing and reading from those instead.
So basically, I think we should change TokenMetadata::read_metadata_from_storage to return TokenMetadata (unless this doesn't work for some reason), and maybe rename it to try_from_storage.
|
Add a temporary setback here on my machine, but plan on finishing this this weeknd. |
8774394 to
2bb8371
Compare
|
The erros in CI onward last commit are regarding crates/miden-agglayer, cause I revoked/reverted the changes as requested! |
…p faucet references
Ah - sorry. I assumed that it would still work correctly as we are not really changing the existing |
|
I rolled back the agglayer code and left a residue of TokenMetadata as before to try and touch it as little as possible. We can them in a future PR adapt it. To make easier reviewing this, since it's too big, we can close this or rebase this if needed. |
PhilippGackstatter
left a comment
There was a problem hiding this comment.
Thanks for the updates!
I left a few more comments, but am still in the process of getting through everything.
| const METADATA_SLOT=word("miden::standards::fungible_faucets::metadata") | ||
| # Note: this slot name should match TOKEN_METADATA_SLOT in metadata/fungible_faucet.masm. | ||
| const METADATA_SLOT=word("miden::standards::metadata::fungible_faucet::token_metadata") |
There was a problem hiding this comment.
We should be able to remove this, make the slot in crates/miden-standards/asm/standards/metadata/fungible_faucet.masm public and then import it here.
crates/miden-standards/asm/standards/metadata/fungible_faucet.masm
Outdated
Show resolved
Hide resolved
crates/miden-standards/asm/standards/metadata/fungible_faucet.masm
Outdated
Show resolved
Hide resolved
crates/miden-standards/asm/standards/metadata/fungible_faucet.masm
Outdated
Show resolved
Hide resolved
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Outdated
Show resolved
Hide resolved
| if max_supply.as_canonical_u64() > FungibleAsset::MAX_AMOUNT { | ||
| return Err(FungibleFaucetError::MaxSupplyTooLarge { | ||
| actual: max_supply.as_canonical_u64(), | ||
| max: FungibleAsset::MAX_AMOUNT, | ||
| }); | ||
| } | ||
| if token_supply.as_canonical_u64() > max_supply.as_canonical_u64() { | ||
| return Err(FungibleFaucetError::TokenSupplyExceedsMaxSupply { |
There was a problem hiding this comment.
We now have new_validated, could we now call it here instead of reimplementing the checks?
Self::new_validated(
symbol,
decimals,
max_supply,
token_supply,
metadata.name.ok_or_else(todo!()),
metadata.description,
metadata.logo_uri,
metadata.external_link,
);
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Outdated
Show resolved
Hide resolved
crates/miden-standards/src/account/metadata/token_metadata/fungible_token/mod.rs
Outdated
Show resolved
Hide resolved
crates/miden-standards/asm/standards/metadata/fungible_faucet.masm
Outdated
Show resolved
Hide resolved
PhilippGackstatter
left a comment
There was a problem hiding this comment.
I think the last merge commit broke a few things like removing some comments in faucets/mod.masm and deleting most of the changelog. Might be best to remove this commit and re-do the merge.
I left a few more comments to simplify the encoding/decoding logic and some structural comments, but overall I think we can soon merge.
I have yet to take a look at most the tests, though.
Unified metadata: One place for account/faucet metadata: token (symbol, decimals, max_supply), owner, name, and content URI. Slot names live under miden::standards::metadata::* (and ownable for owner).
Layout: Token metadata and owner in slots 0–1; name in 2 words (name_0, name_1); content URI in 6 words (content_uri_0..5). Same layout in Rust and MASM.
Faucets: Basic and network fungible faucets support optional name and content URI; both re-export metadata getters (get_name, get_content_uri, get_token_metadata, get_max_supply, get_decimals, get_token_symbol; network also get_owner).
Standalone Info: Non-faucet accounts can use the metadata Info component (name + content URI) for future use (e.g. NFTs).
Testing: Unit tests in miden-standards (metadata storage, recovery); integration tests in miden-testing (MASM getters, faucet + metadata).